import { Toast } from 'antd-mobile'
import axios, { AxiosError } from 'axios'
import { getTokenInfo, removeTokenInfo, setTokenInfo } from './storage'
import history from '@/utils/history'
import store from '@/store'
import { saveToken } from '@/store/actions/login'

const baseURL = 'http://geek.itheima.net/v1_0/'

const instance = axios.create({
  timeout: 5000,
  baseURL,
})

// 拦截器
// 请求拦截器
instance.interceptors.request.use(
  (config) => {
    // 获取token,设置请求头的Authorization字段
    const token = getTokenInfo().token
    if (token) {
      if (config && config?.headers) {
        config.headers.Authorization = 'Bearer ' + token
      }
    }
    return config
  },
  (error) => {
    return Promise.reject(error)
  }
)

// 响应拦截器
instance.interceptors.response.use(
  (response) => {
    return response.data
  },
  async (error: AxiosError<{ message: string }>) => {
    // 网络原因
    if (!error.response) {
      Toast.info('网络繁忙，稍后重试')
      return Promise.reject(error)
    }

    const { response, config } = error
    if (error.response.status !== 401) {
      Toast.info(response.data.message)
      return Promise.reject(error)
    }

    // token失效
    const { refresh_token } = getTokenInfo()
    if (!refresh_token) {
      // 没有token,跳转登录页
      history.replace({
        pathname: '/login',
        state: {
          from: history.location.pathname,
        },
      })
      return Promise.reject(error)
    }

    // 401错误，且有刷新token
    // 尝试发请求获取token
    try {
      // refresh_token有效，且请求token成功
      const res = await axios({
        method: 'put',
        url: baseURL + 'authorizations',
        headers: {
          Authorization: 'Bear ' + refresh_token,
        },
      })
      // 保存新的token , 保存refresh_token
      const tokenInfo = {
        token: res.data.data.token,
        refresh_token: refresh_token,
      }

      store.dispatch({
        type: 'login/token',
        payload: tokenInfo,
      })
      // 保存到redux和localstorage
      store.dispatch(saveToken(tokenInfo))
      setTokenInfo(tokenInfo)

      // 实现无感刷新，把最开始失败的请求重新发一次
      return instance(config)
    } catch (error) {
      // refresh_token过期失效
      // store.dispatch就是Dispatch类型，要求参数要有type才行
      // 移除本地的token
      removeTokenInfo()
      store.dispatch(
        saveToken({
          token: '',
          refresh_token: '',
        })
      )
      // 跳转登录页面
      history.replace({
        pathname: '/login',
        state: {
          from: history.location.pathname,
        },
      })
      Toast.info('登录信息失效，请重新登录')
      // 必须返回失败的Promise，反则程序崩掉
      return Promise.reject(error)
    }
  }
)

export default instance
